#include <memory>
#include <iostream>
#include <brpc/server.h>
#include <butil/logging.h>

#include "base.pb.h"
#include "user.pb.h"
#include "file.pb.h"
#include "friend.pb.h"
#include "gateway.pb.h"
#include "message.pb.h"
#include "notify.pb.h"
#include "speech.pb.h"
#include "transmit.pb.h"

#include "etcder.hpp"
#include "uuid.hpp"
#include "channel.hpp"
#include "logger.hpp"
#include "data_redis.hpp"

#include "connection.hpp"

#include "httplib.h"
namespace bite_im
{
#define GET_PHONE_VERIFY_CODE "/service/user/get_phone_verify_code"
#define USERNAME_REGISTER "/service/user/username_register"
#define USERNAME_LOGIN "/service/user/username_login"
#define PHONE_REGISTER "/service/user/phone_register"
#define PHONE_LOGIN "/service/user/phone_login"
#define GET_USERINFO "/service/user/get_user_info"
#define SET_USER_AVATAR "/service/user/set_avatar"
#define SET_USER_NICKNAME "/service/user/set_nickname"
#define SET_USER_DESC "/service/user/set_description"
#define SET_USER_PHONE "/service/user/set_phone"
#define FRIEND_GET_LIST "/service/friend/get_friend_list"
#define FRIEND_APPLY "/service/friend/add_friend_apply"
#define FRIEND_APPLY_PROCESS "/service/friend/add_friend_process"
#define FRIEND_REMOVE "/service/friend/remove_friend"
#define FRIEND_SEARCH "/service/friend/search_friend"
#define FRIEND_GET_PENDING_EV "/service/friend/get_pending_friend_events"
#define CSS_GET_LIST "/service/friend/get_chat_session_list"
#define CSS_CREATE "/service/friend/create_chat_session"
#define CSS_GET_MEMBER "/service/friend/get_chat_session_member"
#define MSG_GET_RANGE "/service/message_storage/get_history"
#define MSG_GET_RECENT "/service/message_storage/get_recent"
#define MSG_KEY_SEARCH "/service/message_storage/search_history"
#define NEW_MESSAGE "/service/message_transmit/new_message"
#define FILE_GET_SINGLE "/service/file/get_single_file"
#define FILE_GET_MULTI "/service/file/get_multi_file"
#define FILE_PUT_SINGLE "/service/file/put_single_file"
#define FILE_PUT_MULTI "/service/file/put_multi_file"
#define SPEECH_RECOGNITION "/service/speech/recognition"

    class GatewayServer
    {
        using RpcServerPtr = std::shared_ptr<brpc::Server>;

    public:
        using ptr = std::shared_ptr<GatewayServer>;
        GatewayServer(int web_port,
                      int http_port,
                      const RedisPtr &redis_client,
                      const Discovery::ptr &dis_client,
                      const ServiceManager::ptr &service_manager,
                      const std::string &file_service_name,
                      const std::string &user_service_name,
                      const std::string &speech_service_name,
                      const std::string &transmit_service_name,
                      const std::string &message_service_name,
                      const std::string &friend_service_name)
            : _redis_session(std::make_shared<Session>(redis_client)),
              _redis_status(std::make_shared<Status>(redis_client)),
              _dis_client(dis_client),
              _service_manager(service_manager),
              _file_service_name(file_service_name),
              _user_service_name(user_service_name),
              _speech_service_name(speech_service_name),
              _transmit_service_name(transmit_service_name),
              _message_service_name(message_service_name),
              _friend_service_name(friend_service_name)
        {
            // 搭建web_sock服务器

            // 初始化日志输出---关闭
            _websock_server.set_access_channels(websocketpp::log::alevel::none);
            // 初始化asio框架
            _websock_server.init_asio();
            // 设置连接建立、断开、获取消息回调函数
            auto webOnOpen = std::bind(&GatewayServer::web_onOpen, this, std::placeholders::_1);
            auto webOnClose = std::bind(&GatewayServer::web_onClose, this, std::placeholders::_1);
            auto webOnMessage = std::bind(&GatewayServer::web_onBuildConn, this, std::placeholders::_1, std::placeholders::_2);

            _websock_server.set_open_handler(webOnOpen);
            _websock_server.set_close_handler(webOnClose);
            _websock_server.set_message_handler(webOnMessage);
            // 设置地址重用
            _websock_server.set_reuse_addr(true);
            // 设置监听端口
            _websock_server.listen(web_port);
            _websock_server.start_accept();

            // 搭建http服务器

            // 设置回调函数，收到访问什么的请求就调用哪个回调函数
            {
                _http_server.Post(GET_PHONE_VERIFY_CODE, (httplib::Server::Handler)std::bind(&GatewayServer::GetPhoneVerifyCode, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(USERNAME_REGISTER, (httplib::Server::Handler)std::bind(&GatewayServer::UserRegister, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(USERNAME_LOGIN, (httplib::Server::Handler)std::bind(&GatewayServer::UserLogin, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(PHONE_REGISTER, (httplib::Server::Handler)std::bind(&GatewayServer::PhoneRegister, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(PHONE_LOGIN, (httplib::Server::Handler)std::bind(&GatewayServer::PhoneLogin, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(GET_USERINFO, (httplib::Server::Handler)std::bind(&GatewayServer::GetUserInfo, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_AVATAR, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserAvatar, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_NICKNAME, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserNickname, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_DESC, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserDescription, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SET_USER_PHONE, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserPhoneNumber, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_GET_LIST, (httplib::Server::Handler)std::bind(&GatewayServer::GetFriendList, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_APPLY, (httplib::Server::Handler)std::bind(&GatewayServer::FriendAdd, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_APPLY_PROCESS, (httplib::Server::Handler)std::bind(&GatewayServer::FriendAddProcess, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_REMOVE, (httplib::Server::Handler)std::bind(&GatewayServer::FriendRemove, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_SEARCH, (httplib::Server::Handler)std::bind(&GatewayServer::FriendSearch, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FRIEND_GET_PENDING_EV, (httplib::Server::Handler)std::bind(&GatewayServer::GetPendingFriendEventList, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_GET_LIST, (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionList, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_CREATE, (httplib::Server::Handler)std::bind(&GatewayServer::ChatSessionCreate, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(CSS_GET_MEMBER, (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionMember, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_GET_RANGE, (httplib::Server::Handler)std::bind(&GatewayServer::GetHistoryMsg, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_GET_RECENT, (httplib::Server::Handler)std::bind(&GatewayServer::GetRecentMsg, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(MSG_KEY_SEARCH, (httplib::Server::Handler)std::bind(&GatewayServer::MsgSearch, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(NEW_MESSAGE, (httplib::Server::Handler)std::bind(&GatewayServer::NewMessage, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_GET_SINGLE, (httplib::Server::Handler)std::bind(&GatewayServer::GetSingleFile, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_GET_MULTI, (httplib::Server::Handler)std::bind(&GatewayServer::GetMultiFile, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_PUT_SINGLE, (httplib::Server::Handler)std::bind(&GatewayServer::PutSingleFile, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(FILE_PUT_MULTI, (httplib::Server::Handler)std::bind(&GatewayServer::PutMultiFile, this, std::placeholders::_1, std::placeholders::_2));
                _http_server.Post(SPEECH_RECOGNITION, (httplib::Server::Handler)std::bind(&GatewayServer::SpeechRecognition, this, std::placeholders::_1, std::placeholders::_2));
            }

            // 通过新线程来进行监听
            _http_thread = std::thread([this, http_port]()
                                       { _http_server.listen("0.0.0.0", http_port); });
            _http_thread.detach();
            // server.Post()
            //  3. 启动服务器
        }
        ~GatewayServer() {}

        // 启动webSock服务器
        void start()
        {
            _websock_server.run();
        }

    private:
        // --------------------------------------------------http的回调函数-----------------------------------------------------

        // 用户子服务接口

        void GetPhoneVerifyCode(const httplib::Request &request, httplib::Response &response)
        {
            // 构建GetPhoneVerifyCode请求和响应
            PhoneVerifyCodeReq req;
            PhoneVerifyCodeRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetPhoneVerifyCode的http请求反序列化失败");
                return err_response_func("GetPhoneVerifyCode的http请求反序列化失败");
            }
            // 2.调用GetPhoneVerifyCode请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetPhoneVerifyCode的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("GetPhoneVerifyCode的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和PhoneVerifyCodeReq一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 3.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); // 正文类型"application/x-protbuf"
        }
        void UserRegister(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            UserRegisterReq req;
            UserRegisterRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("UserRegister的http请求反序列化失败");
                return err_response_func("UserRegister的http请求反序列化失败");
            }
            // 2.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("UserRegister的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("UserRegister的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.UserRegister(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 3.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); // 正文类型"application/x-protbuf"
        }
        void UserLogin(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            UserLoginReq req;
            UserLoginRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("UserLogin的http请求反序列化失败");
                return err_response_func("UserLogin的http请求反序列化失败");
            }
            // 2.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("UserLogin的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("UserLogin的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.UserLogin(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }

            // 这里默认已经登陆成功，但是可能出现重复登录的场景，所以我们可以在Login的响应添加一个ifLoad
            // 如果ifLoad == true
            
            // if(rsp.ifLoad() == true)
            // {
            //     // 这里我们需要通过user_id来释放conn链接
            //     auto conn = _conntions->connection(rsp.user_id);
            //     // 找到旧的会话id
            //     std::string uid, session_id;
            //     _connections->cilent(conn, session_id, uid);
            //     // 删除这个键
            //     _redis_session->remove(ssid);
            //     _connections->remove(conn);
            //     conn->close(websocketpp::close::status::normal, "其他主机已经登陆")；
            // }

            // 3.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); // 正文类型"application/x-protbuf"
        }
        void PhoneRegister(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            PhoneRegisterReq req;
            PhoneRegisterRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("PhoneRegister的http请求反序列化失败");
                return err_response_func("PhoneRegister的http请求反序列化失败");
            }
            // 2.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("PhoneRegister的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("PhoneRegister的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.PhoneRegister(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 3.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); // 正文类型"application/x-protbuf"
        }
        void PhoneLogin(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            PhoneLoginReq req;
            PhoneLoginRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("PhoneLogin的http请求反序列化失败");
                return err_response_func("PhoneLogin的http请求反序列化失败");
            }
            // 2.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("PhoneLogin的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("PhoneLogin的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.PhoneLogin(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 3.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf"); // 正文类型"application/x-protbuf"
        }
        // 需要额外进行客户端身份识别 和 用户id的填充
        void GetUserInfo(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetUserInfoReq req;
            GetUserInfoRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetUserInfo的http请求反序列化失败");
                return err_response_func("GetUserInfo的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetUserInfo获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetUserInfo的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetUserInfo的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("GetUserInfo的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 4.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void SetUserAvatar(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            SetUserAvatarReq req;
            SetUserAvatarRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("SetUserAvatar的http请求反序列化失败");
                return err_response_func("SetUserAvatar的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("SetUserAvatar获取会话[{}]的用户信息失败", session_id);
                return err_response_func("SetUserAvatar的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("SetUserAvatar的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("SetUserAvatar的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 4.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void SetUserNickname(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            SetUserNicknameReq req;
            SetUserNicknameRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("SetUserNickname的http请求反序列化失败");
                return err_response_func("SetUserNickname的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("SetUserNickname获取会话[{}]的用户信息失败", session_id);
                return err_response_func("SetUserNickname的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("SetUserNickname的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("SetUserNickname的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.SetUserNickname(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 4.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void SetUserDescription(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            SetUserDescriptionReq req;
            SetUserDescriptionRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("SetUserDescription的http请求反序列化失败");
                return err_response_func("SetUserDescription的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("SetUserDescription获取会话[{}]的用户信息失败", session_id);
                return err_response_func("SetUserDescription的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("SetUserDescription的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("SetUserDescription的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.SetUserDescription(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 4.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void SetUserPhoneNumber(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            SetUserPhoneNumberReq req;
            SetUserPhoneNumberRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("SetUserPhoneNumber的http请求反序列化失败");
                return err_response_func("SetUserPhoneNumber的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("SetUserPhoneNumber获取会话[{}]的用户信息失败", session_id);
                return err_response_func("SetUserPhoneNumber的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_user_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("SetUserPhoneNumber的用户子服务[{}]不存在", _user_service_name);
                return err_response_func("SetUserPhoneNumber的用户子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.SetUserPhoneNumber(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("用户子服务调用失败");
            }
            // 4.得到用户子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 好友子服务接口
        // 不涉及通知事件
        void GetFriendList(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetFriendListReq req;
            GetFriendListRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetFriendList的http请求反序列化失败");
                return err_response_func("GetFriendList的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetFriendList获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetFriendList的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetFriendList的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("GetFriendList的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetFriendList(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void FriendSearch(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            FriendSearchReq req;
            FriendSearchRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("FriendSearch的http请求反序列化失败");
                return err_response_func("FriendSearch的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("FriendSearch获取会话[{}]的用户信息失败", session_id);
                return err_response_func("FriendSearch的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("FriendSearch的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("FriendSearch的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.FriendSearch(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void GetPendingFriendEventList(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetPendingFriendEventListReq req;
            GetPendingFriendEventListRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetPendingFriendEventList的http请求反序列化失败");
                return err_response_func("GetPendingFriendEventList的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetPendingFriendEventList获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetPendingFriendEventList的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetPendingFriendEventList的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("GetPendingFriendEventList的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void GetChatSessionList(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetChatSessionListReq req;
            GetChatSessionListRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetChatSessionList的http请求反序列化失败");
                return err_response_func("GetChatSessionList的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetChatSessionList获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetChatSessionList的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetChatSessionList的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("GetChatSessionList的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void GetChatSessionMember(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetChatSessionMemberReq req;
            GetChatSessionMemberRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetChatSessionMember的http请求反序列化失败");
                return err_response_func("GetChatSessionMember的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetChatSessionMember获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetChatSessionMember的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetChatSessionMember的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("GetChatSessionMember的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 发送请求时，需要给被请求方进行消息推送，例如申请crush为好友，要让crush知道
        void FriendAdd(const httplib::Request &request, httplib::Response &response) 
        {
            // 构建调用接口请求和响应
            FriendAddReq req;
            FriendAddRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("FriendAdd的http请求反序列化失败");
                return err_response_func("FriendAdd的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("FriendAdd获取会话[{}]的用户信息失败", session_id);
                return err_response_func("FriendAdd的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("FriendAdd的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("FriendAdd的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.FriendAdd(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.进行FriendAdd的消息通知，获取长连接
            auto conn = _connections->connection(req.respondent_id()); // 如果找不到长连接，说明用户还没有上线
            if (conn)                                                  // 表示长连接存在
            {
                // 5.调用用户子服务获得用户信息
                auto user_rsp = getUserInfo(req.request_id(), *user_id);
                if (user_rsp.get() == nullptr)
                {
                    LOG_ERROR("获取用户[{}]信息失败", *user_id);
                    return err_response_func("获取用户信息失败");
                }

                // 6.构建NotifyMessage通知对象
                NotifyMessage notify;
                notify.set_notify_type(NotifyType::FRIEND_ADD_APPLY_NOTIFY);
                notify.mutable_friend_add_apply()->mutable_user_info()->CopyFrom(user_rsp->user_info());

                // 7.通过websock进行消息推送NotifyMessage对象
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }

            // 8.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void FriendAddProcess(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            FriendAddProcessReq req;
            FriendAddProcessRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("FriendAddProcess的http请求反序列化失败");
                return err_response_func("FriendAddProcess的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("FriendAddProcess获取会话[{}]的用户信息失败", session_id);
                return err_response_func("FriendAddProcess的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);

            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("FriendAddProcess的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("FriendAddProcess的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.进行FriendAdd的消息通知，获取长连接
            auto process_conn = _connections->connection(*user_id);          // 处理人当前长连接
            auto apply_conn = _connections->connection(req.apply_user_id()); // 申请人当前长连接

            // 5.调用用户子服务获得用户信息
            auto process_user_rsp = getUserInfo(req.request_id(), *user_id);
            if (process_user_rsp.get() == nullptr)
            {
                LOG_ERROR("获取用户[{}]信息失败", *user_id);
                return err_response_func("获取用户信息失败");
            }

            auto apply_user_rsp = getUserInfo(req.request_id(), req.apply_user_id());
            if (apply_user_rsp.get() == nullptr)
            {
                LOG_ERROR("获取用户[{}]信息失败", req.apply_user_id());
                return err_response_func("获取用户信息失败");
            }

            // 如果长连接存在，通过长连接来向对应用户发送通知事件
            if (apply_conn)
            {
                NotifyMessage notify;
                notify.set_notify_type(NotifyType::FRIEND_ADD_PROCESS_NOTIFY);
                notify.mutable_friend_process_result()->mutable_user_info()->CopyFrom(process_user_rsp->user_info());
                notify.mutable_friend_process_result()->set_agree(req.agree());
                // 向申请人发送 FriendAddProcess处理人信息和处理结果
                apply_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }
            /*
                在FriendAdd中，小明向小红发送好友申请，就需要网关通知小红，小明要加他，所以是小明对应的信息发送给小红
                在当前模块，在小红处理这个请求时，小红是process_user，小明为apply_user，那么这个时候，网关要通知小明它的申请结果是什么？
                所以是通过小明的长连接给小明发送小红信息和处理结果！
            */

            // 好友处理通知发送 如果为同意那么需要给双方进行聊天会话创建的通知
            if (req.agree() == true && apply_conn)
            {
                NotifyMessage notify;
                notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_single_chat_friend_id(*user_id);
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_chat_session_name(process_user_rsp->user_info().nickname());
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_avatar(process_user_rsp->user_info().avatar());
                // 7.通过websock进行消息推送NotifyMessage对象
                apply_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }
            if (req.agree() == true && process_conn)
            {
                NotifyMessage notify;
                notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_single_chat_friend_id(req.apply_user_id());
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_chat_session_name(apply_user_rsp->user_info().nickname());
                notify.mutable_new_chat_session_info()->mutable_chat_session_info()->set_avatar(apply_user_rsp->user_info().avatar());
                // 7.通过websock进行消息推送NotifyMessage对象
                process_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }

            // 8.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void FriendRemove(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            FriendRemoveReq req;
            FriendRemoveRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("FriendRemove的http请求反序列化失败");
                return err_response_func("FriendRemove的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("FriendRemove获取会话[{}]的用户信息失败", session_id);
                return err_response_func("FriendRemove的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("FriendRemove的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("FriendRemove的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.FriendRemove(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 4.进行FriendAdd的消息通知，获取长连接
            auto conn = _connections->connection(req.peer_id()); // 如果找不到长连接，说明用户还没有上线
            if (conn)                                            // 表示长连接存在
            {
                // 6.构建NotifyMessage通知对象
                NotifyMessage notify;
                notify.set_notify_type(NotifyType::FRIEND_REMOVE_NOTIFY);
                notify.mutable_friend_remove()->set_user_id(*user_id);

                // 7.通过websock进行消息推送NotifyMessage对象
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }

            // 8.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void ChatSessionCreate(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            ChatSessionCreateReq req;
            ChatSessionCreateRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("ChatSessionCreate的http请求反序列化失败");
                return err_response_func("ChatSessionCreate的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("ChatSessionCreate获取会话[{}]的用户信息失败", session_id);
                return err_response_func("ChatSessionCreate的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给用户子服务进行业务处理
            auto channel = _service_manager->choose(_friend_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("ChatSessionCreate的好友子服务[{}]不存在", _friend_service_name);
                return err_response_func("ChatSessionCreate的好友子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("好友子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("好友子服务调用失败");
            }
            // 创建群聊后，通过member_id_list来进行循环消息通知
            for (int i = 0; i < req.member_id_list_size(); i++)
            {
                // 4.进行FriendAdd的消息通知，获取长连接
                auto conn = _connections->connection(req.member_id_list(i)); // 如果找不到长连接，说明用户还没有上线
                if (conn)                                                    // 表示长连接存在
                {
                    // 6.构建NotifyMessage通知对象
                    NotifyMessage notify;
                    notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                    notify.mutable_new_chat_session_info()->mutable_chat_session_info()->CopyFrom(rsp.chat_session_info());
                    // 7.通过websock进行消息推送NotifyMessage对象
                    conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                }
            }
            rsp.clear_chat_session_info(); // 清理掉chat_session_info，前端不需要，可以减小数据包，传输速度增大
            // 8.得到好友子服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 消息存储子服务接口
        void GetHistoryMsg(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetHistoryMsgReq req;
            GetHistoryMsgRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetHistoryMsg的http请求反序列化失败");
                return err_response_func("GetHistoryMsg的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetHistoryMsg获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetHistoryMsg的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给消息存储子服务进行业务处理
            auto channel = _service_manager->choose(_message_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetHistoryMsg的消息存储子服务[{}]不存在", _message_service_name);
                return err_response_func("GetHistoryMsg的消息存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            MsgStorageService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetHistoryMsg(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("消息存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("消息存储子服务调用失败");
            }
            // 4.得到消息存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void GetRecentMsg(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetRecentMsgReq req;
            GetRecentMsgRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetRecentMsg的http请求反序列化失败");
                return err_response_func("GetRecentMsg的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetRecentMsg获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetRecentMsg的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给消息存储子服务进行业务处理
            auto channel = _service_manager->choose(_message_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetRecentMsg的消息存储子服务[{}]不存在", _message_service_name);
                return err_response_func("GetRecentMsg的消息存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            MsgStorageService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("消息存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("消息存储子服务调用失败");
            }
            // 4.得到消息存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void MsgSearch(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            MsgSearchReq req;
            MsgSearchRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("MsgSearch的http请求反序列化失败");
                return err_response_func("MsgSearch的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("MsgSearch获取会话[{}]的用户信息失败", session_id);
                return err_response_func("MsgSearch的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给消息存储子服务进行业务处理
            auto channel = _service_manager->choose(_message_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("MsgSearch的消息存储子服务[{}]不存在", _message_service_name);
                return err_response_func("MsgSearch的消息存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            MsgStorageService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.MsgSearch(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("消息存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("消息存储子服务调用失败");
            }
            // 4.得到消息存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 消息转发子服务接口
        void NewMessage(const httplib::Request &request, httplib::Response &response)
        {
            /*  接口场景：前端向后端发送

                    前端准备好发送的信息结构和聊天会话id，发送给网关填入用户信息，接着网关通过
                    消息转发子服务的GetTransmitTarget获得一个转发列表，并将这个消息放到消息队列mq里面,
                    与此同时消息存储子服务通过回调函数，在这个mq队列中消费这条消息，存储这条消息。
                    并且网关也向当前聊天会话内的所有成员发起新消息的通知，消息内容伴随这个通知也推送过去
            */

            // 构建调用接口请求和响应
            NewMessageReq req;
            NewMessageRsp rsp;
            GetTransmitTargetRsp target_rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("NewMessage的http请求反序列化失败");
                return err_response_func("NewMessage的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("NewMessage获取会话[{}]的用户信息失败", session_id);
                return err_response_func("NewMessage的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给消息转发子服务进行业务处理
            auto channel = _service_manager->choose(_transmit_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("NewMessage的消息转发子服务[{}]不存在", _transmit_service_name);
                return err_response_func("NewMessage的消息转发子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            MsgTransmitService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetTransmitTarget(&cntl, &req, &target_rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("消息转发子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("消息转发子服务调用失败");
            }
            // 此时target_rsp获得了转发目标，通过WebSock来进行实时通知！
            for (int i = 0; i < target_rsp.target_id_list_size(); i++)
            {
                // 4.获得新消息-进行消息通知，获取长连接
                auto conn = _connections->connection(target_rsp.target_id_list(i));
                if (conn)
                {
                    // 6.构建NotifyMessage通知对象
                    NotifyMessage notify;
                    notify.set_notify_type(NotifyType::CHAT_MESSAGE_NOTIFY);
                    // 消息跟着通知事件推送给客户端
                    notify.mutable_new_message_info()->mutable_message_info()->CopyFrom(target_rsp.message());
                    // 7.通过websock进行消息推送NotifyMessage对象
                    conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                }
            }

            rsp.set_request_id(req.request_id());
            rsp.set_success(target_rsp.success());
            rsp.set_errmsg(target_rsp.errmsg());
            // 4.得到消息转发服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 文件管理子服务接口
        void GetSingleFile(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetSingleFileReq req;
            GetSingleFileRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetSingleFile的http请求反序列化失败");
                return err_response_func("GetSingleFile的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetSingleFile获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetSingleFile的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给文件存储子服务进行业务处理
            auto channel = _service_manager->choose(_file_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetSingleFile的文件存储子服务[{}]不存在", _file_service_name);
                return err_response_func("GetSingleFile的文件存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FileService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetSingleFile(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("文件存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("文件存储子服务调用失败");
            }
            // 4.得到文件存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void GetMultiFile(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            GetMultiFileReq req;
            GetMultiFileRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("GetMultiFile的http请求反序列化失败");
                return err_response_func("GetMultiFile的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("GetMultiFile获取会话[{}]的用户信息失败", session_id);
                return err_response_func("GetMultiFile的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给文件存储子服务进行业务处理
            auto channel = _service_manager->choose(_file_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("GetMultiFile的文件存储子服务[{}]不存在", _file_service_name);
                return err_response_func("GetMultiFile的文件存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FileService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetMultiFile(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("文件存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("文件存储子服务调用失败");
            }
            // 4.得到文件存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void PutSingleFile(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            PutSingleFileReq req;
            PutSingleFileRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("PutSingleFile的http请求反序列化失败");
                return err_response_func("PutSingleFile的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("PutSingleFile获取会话[{}]的用户信息失败", session_id);
                return err_response_func("PutSingleFile的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给文件存储子服务进行业务处理
            auto channel = _service_manager->choose(_file_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("PutSingleFile的文件存储子服务[{}]不存在", _file_service_name);
                return err_response_func("PutSingleFile的文件存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FileService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.PutSingleFile(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("文件存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("文件存储子服务调用失败");
            }
            // 4.得到文件存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }
        void PutMultiFile(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            PutMultiFileReq req;
            PutMultiFileRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("PutMultiFile的http请求反序列化失败");
                return err_response_func("PutMultiFile的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("PutMultiFile获取会话[{}]的用户信息失败", session_id);
                return err_response_func("PutMultiFile的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给文件存储子服务进行业务处理
            auto channel = _service_manager->choose(_file_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("PutMultiFile的文件存储子服务[{}]不存在", _file_service_name);
                return err_response_func("PutMultiFile的文件存储子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            FileService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.PutMultiFile(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("文件存储子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("文件存储子服务调用失败");
            }
            // 4.得到文件存储服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // 语音转文字子服务接口
        void SpeechRecognition(const httplib::Request &request, httplib::Response &response)
        {
            // 构建调用接口请求和响应
            SpeechRecognitionReq req;
            SpeechRecognitionRsp rsp;
            auto err_response_func = [&req, &rsp, &response](const std::string &errmsg) -> void
            {
                rsp.set_success(false);
                rsp.set_errmsg(errmsg);
                response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            };
            // 1.网关从网络中（对方客户端）获取数据，并反序列化为结构体
            bool ret = req.ParseFromString(request.body);
            // 反序列化失败
            if (ret == false)
            {
                LOG_ERROR("SpeechRecognition的http请求反序列化失败");
                return err_response_func("SpeechRecognition的http请求反序列化失败");
            }
            // 2.客户端身份识别和填充
            std::string session_id = req.session_id(); // 从请求中获取登录会话id
            auto user_id = _redis_session->uid(session_id);
            if (!user_id) // 表示不存在这个用户信息
            {
                LOG_ERROR("SpeechRecognition获取会话[{}]的用户信息失败", session_id);
                return err_response_func("SpeechRecognition的http请求反序列化失败");
            }
            // 用户信息存在，添加到请求中
            req.set_user_id(*user_id);
            // 3.调用接口请求给语音转文字子服务进行业务处理
            auto channel = _service_manager->choose(_speech_service_name);
            if (channel.get() == nullptr) // !channel
            {
                LOG_ERROR("SpeechRecognition的语音转文字子服务[{}]不存在", _speech_service_name);
                return err_response_func("SpeechRecognition的语音转文字子服务不存在");
            }
            // 此时req就是通过request反序列化成功得到的请求     --- 默认客户端发来的请求的结构和接口请求一致
            SpeechService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.SpeechRecognition(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false)
            {
                LOG_ERROR("语音转文字子服务调用失败，原因[{}]", cntl.ErrorText());
                return err_response_func("语音转文字子服务调用失败");
            }
            // 4.得到语音转文字服务响应后，序列化发送给客户端
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        }

        // bool getUserInfo(const std::string &request_id, const std::string &user_id, UserInfo &user)
        std::shared_ptr<GetUserInfoRsp> getUserInfo(const std::string &request_id, const std::string &user_id)
        {
            GetUserInfoReq req;
            req.set_request_id(request_id);
            req.set_user_id(user_id);
            auto rsp = std::make_shared<GetUserInfoRsp>(); // 用智能指针维护，减少第728行存在的数据拷贝
            auto channel = _service_manager->choose(_user_service_name);
            if (!channel) // 服务不存在
            {
                LOG_ERROR("用户子服务[{}]节点未找到", _user_service_name);
                return rsp;
            }
            UserService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetUserInfo(&cntl, &req, rsp.get(), nullptr);
            if (cntl.Failed() == true || rsp->success() == false)
            {
                LOG_ERROR("用户子服务调用失败，原因[{}]", cntl.ErrorText());
            }
            // user = rsp.user_info();
            return rsp;
        }

    private:
        // --------------------------------------------------webSock的回调函数-----------------------------------------------------
        void web_onOpen(websocketpp::connection_hdl hdl)
        {
            LOG_DEBUG("websocket长连接建立成功[{}]", (size_t)_websock_server.get_con_from_hdl(hdl).get());
        }
        void web_onClose(websocketpp::connection_hdl hdl)
        {
            // 长连接断开时做的清理工作
            // 0. 通过连接对象，获取对应的用户ID与登录会话ID
            auto conn = _websock_server.get_con_from_hdl(hdl);
            std::string uid, ssid;
            bool ret = _connections->client(conn, uid, ssid);
            if (ret == false)
            {
                LOG_WARN("长连接断开，未找到长连接对应的客户端信息");
                return;
            }
            // 1. 移除登录会话信息
            _redis_session->remove(ssid);
            // 2. 移除登录状态信息
            _redis_status->remove(uid);
            // 3. 移除长连接管理数据
            _connections->remove(conn);
            LOG_DEBUG("[{}]-[{}]-[{}] 长连接断开，清理缓存数据", ssid, uid, (size_t)conn.get());
        }
        
        void web_onBuildConn(websocketpp::connection_hdl hdl, server_t::message_ptr mesg)
        {
            // 收到第一条消息后，根据消息中的会话ID进行身份识别，将客户端长连接添加管理
            // 1. 取出长连接对应的连接对象
            auto conn = _websock_server.get_con_from_hdl(hdl);
            // 2. 针对消息内容进行反序列化 -- ClientAuthenticationReq -- 提取登录会话ID
            ClientAuthenticationReq request;
            bool ret = request.ParseFromString(mesg->get_payload());
            if (ret == false)
            {
                LOG_ERROR("长连接身份识别失败：正文反序列化失败");
                _websock_server.close(hdl, websocketpp::close::status::unsupported_data, "正文反序列化失败");
                return;
            }
            // 3. 在会话信息缓存中，查找会话信息
            std::string ssid = request.session_id();
            auto uid = _redis_session->uid(ssid);
            // 4. 会话信息不存在则关闭连接
            if (!uid)
            {
                LOG_ERROR("长连接身份识别失败：未找到会话信息[{}]", ssid);
                _websock_server.close(hdl, websocketpp::close::status::unsupported_data, "未找到会话信息");
                return;
            }
            // 5. 会话信息存在，则添加长连接管理
            _connections->insert(conn, *uid, ssid);
            LOG_DEBUG("新增长连接管理：[{}]-[{}]-[{}]", ssid, *uid, (size_t)conn.get());
            keepAlive(conn);
        }

        void keepAlive(server_t::connection_ptr conn)
        {
            if (!conn || conn->get_state() != websocketpp::session::state::value::open)
            {
                LOG_DEBUG("非正常连接状态，结束连接保活");
                return;
            }
            conn->ping(""); // 定期发送ping报文
            _websock_server.set_timer(60000, std::bind(&GatewayServer::keepAlive, this, conn));
        }

    private:
    
        // 项目运行期间都需要持续维护这些对象
        Discovery::ptr _dis_client; // 服务发现

        // redis存储
        Session::ptr _redis_session;
        Status::ptr _redis_status;

        // rpc获取用户子服务
        std::string _file_service_name;
        std::string _user_service_name;
        std::string _speech_service_name;
        std::string _transmit_service_name;
        std::string _message_service_name;
        std::string _friend_service_name;
        ServiceManager::ptr _service_manager;

        // 长连接对象
        Connection::ptr _connections;

        // websock长连接响应服务器
        bite_im::server_t _websock_server;
        // http响应服务器
        httplib::Server _http_server;
        // http工作线程
        std::thread _http_thread;
    };

    /*建造者设计模式，封装对象的构造过程，防止用户在进行操作时，对未构造的对象进行操作*/

    class GatewayServerBuilder
    {
        using RpcServerPtr = std::shared_ptr<brpc::Server>;

    public:
        void make_redis_object(const std::string &redis_ip, int redis_port, bool keep_alive, int db_flag)
        {
            _redis_client = RedisFactory::create(redis_ip, redis_port, keep_alive, db_flag);
        }

        // 构造服务发现和服务管理客户端
        void make_find_object(const std::string &reg_host,
                              const std::string &base_service_name,
                              const std::string &file_service_name,
                              const std::string &user_service_name,
                              const std::string &speech_service_name,
                              const std::string &transmit_service_name,
                              const std::string &message_service_name,
                              const std::string &friend_service_name)
        {
            _file_service_name = file_service_name;
            _user_service_name = user_service_name;
            _speech_service_name = speech_service_name;
            _transmit_service_name = transmit_service_name;
            _message_service_name = message_service_name;
            _friend_service_name = friend_service_name;
            _service_manager = std::make_shared<ServiceManager>();
            _service_manager->declareService(file_service_name);
            _service_manager->declareService(user_service_name);
            _service_manager->declareService(speech_service_name);
            _service_manager->declareService(transmit_service_name);
            _service_manager->declareService(message_service_name);
            _service_manager->declareService(friend_service_name);
            LOG_INFO("服务发现模块中添加了文件管理子服务[{}]", file_service_name);
            LOG_INFO("服务发现模块中添加了用户管理子服务[{}]", user_service_name);
            LOG_INFO("服务发现模块中添加了语音转文字子服务[{}]", speech_service_name);
            LOG_INFO("服务发现模块中添加了消息转发子服务[{}]", transmit_service_name);
            LOG_INFO("服务发现模块中添加了消息存储子服务[{}]", message_service_name);
            LOG_INFO("服务发现模块中添加了好友管理子服务[{}]", friend_service_name);

            auto put_cb = std::bind(&bite_im::ServiceManager::onServiceOnline, _service_manager.get(),
                                    std::placeholders::_1, std::placeholders::_2);
            auto del_cb = std::bind(&bite_im::ServiceManager::onServiceOffLine, _service_manager.get(),
                                    std::placeholders::_1, std::placeholders::_2);
            _dis_client = std::make_shared<Discovery>(base_service_name, reg_host, put_cb, del_cb);
        }

        // 获取webSock的端口，http的端口
        void get_gateway_port(int web_port, int http_port)
        {
            _web_port = web_port;
            _http_port = http_port;
        }

        GatewayServer::ptr build()
        {
            // 检测维护对象是否建立
            if (_dis_client.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未初始化服务发现模块"); // 发现是否子服务由新增或者下线
                abort();
            }
            if (_redis_client.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未初始化redis模块");
                abort();
            }
            if (_service_manager.get() == nullptr)
            {
                LOG_ERROR("服务器建造失败，未初始化服务管理模块");
                abort();
            }

            GatewayServer::ptr server = std::make_shared<GatewayServer>(_web_port, _http_port, _redis_client, _dis_client, _service_manager,
                                                                        _file_service_name, _user_service_name, _speech_service_name,
                                                                        _transmit_service_name, _message_service_name, _friend_service_name);
            return server;
        }

    private:
        int _web_port;
        int _http_port;
        // redis模块
        RedisPtr _redis_client;

        // 服务注册和发现模块
        std::string _file_service_name;
        std::string _user_service_name;
        std::string _speech_service_name;
        std::string _transmit_service_name;
        std::string _message_service_name;
        std::string _friend_service_name;
        ServiceManager::ptr _service_manager;

        Discovery::ptr _dis_client;
    };
}